/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Rewriting;

import RPS.PeerSchema;
import SPARQL.Constant;
import SPARQL.SPARQL;
import SPARQL.TriplePattern;
import java.util.HashSet;
import java.util.Set;

/**
 *
 * @author mirko
 */
public class FederationManager {
    
    private Set<Source> sources;

    public FederationManager(Set<Source> sources) {
        this.sources = sources;
    }

    public FederationManager() {
        this.sources = new HashSet<Source>();
    }
    
    public boolean addSource (Source source){
        return this.sources.add(source);
    }
    
    
    
    public Set<SPARQL> rewrite(Set<SPARQL> queryList){
        //todo
        Set<SPARQL> rewrittenList = new HashSet<SPARQL>(queryList);
        
        for (SPARQL query : rewrittenList){
            for (TriplePattern triple : query.getTriplePatterns()){
                Set<Constant> constants = triple.getConstants();
                outerloop:
                for (Source source : this.sources)
                    if (source.getSchema().contains(constants)){
                        
                        query.addSerivice(source.getEndpoint(), triple);
                        break outerloop;
                        
                    }
                        
                
            }
            
                
            
        }
        
    return rewrittenList;
    
    }
    public SPARQL rewrite(SPARQL query){
        //todo
        Set<SPARQL> rewrittenList = new HashSet<SPARQL>();
        rewrittenList.add(query);
        
        for (SPARQL queryit : rewrittenList){
            for (TriplePattern triple : queryit.getTriplePatterns()){
                Set<Constant> constants = triple.getConstants();
                outerloop:
                for (Source source : this.sources)
                    if (source.getSchema().contains(constants)){
                        
                        queryit.addSerivice(source.getEndpoint(), triple);
                        break outerloop;
                        
                    }
                        
                
            }
            
                
            
        }
        
    return rewrittenList.iterator().next();
        
        
    }
    
    public Set<SPARQL> rewriteMultiple(SPARQL query){
        
        Set<SPARQL> rewrittenqueries = new HashSet<SPARQL>();
        SPARQL queryclone = (SPARQL) query.clone();
        rewrittenqueries.add(queryclone);
        Set<SPARQL> rewrittenqueryIteration = new HashSet<SPARQL>();
        rewrittenqueryIteration.add(queryclone);
        
        for (TriplePattern triple : query.getTriplePatterns()){
            for (SPARQL queryiteration: rewrittenqueryIteration){
                rewrittenqueries.remove(queryiteration);
                
                
                Set<Constant> constants = triple.getConstants();
                
                for (Source source : this.sources){
                    if (source.getSchema().contains(constants)){
                        SPARQL queryIterationrewritten = (SPARQL) queryiteration.clone();
                        
                        queryIterationrewritten.addSerivice(source.getEndpoint(), triple);
                        rewrittenqueries.add(queryIterationrewritten);
                        
                        
                    }
                    
                }
            }
            
            rewrittenqueryIteration = new HashSet<SPARQL>();
            rewrittenqueryIteration.addAll(rewrittenqueries);
        }
        
        return rewrittenqueries;
    }
     
     /*
     Riscrive la query inserendo la SERVICE clause. A differenza del metodo non-multiplo, qui consideriamo anche il fatto che un triple pattern possa essere inviato a due 
     endpoints diversi. 
     */
      public Set<SPARQL> rewriteMultiple(Set<SPARQL> queryList){
        //todo
        Set<SPARQL> rewrittenList = new HashSet<SPARQL>();
        
        for (SPARQL query : queryList){
            rewrittenList.addAll(rewriteMultiple(query));
            
                
            
        }
        
    return rewrittenList;
    
    }
     
     
     
}
